/*
Copyright (c) 2006 - 2008  Universitaet Osnabrueck, virtUOS
Authors: Markus Ketterl, Johannes Emden, Nils Schuhmacher, Andreas Rickling

This file is part of virtPresenter.

virtPresenter is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

virtPresenter is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with virtPresenter.  If not, see <http://www.gnu.org/licenses/>.
*/

package virtPresenter.model
{
	import flash.events.EventDispatcher;

	[Bindable]
	/**
	 * The XMLParser has functions that help finding timesteps of the slides.
	 */
	public class XMLParser extends EventDispatcher
	{				
		public var timeSteps:Array;
		public var mouseSteps:Array;
		public var mouseXMLAvailable:Boolean;
		public var slides:Array;
		private var tmp:int;	
		private var lastJ:int=0;
		private var lastJMouseXML:int=0;		
		
		private var locator : virtPresenterLocator = virtPresenterLocator.getInstance();		
		
		public function XMLParser()
		{		
			timeSteps = new Array();
			mouseXMLAvailable=false;
		}				
				
		public function files_both_loaded():void
		{		
				extractSlides();
				locator.xmlReceived=true;  
				locator.defaultView.videoPlayer.doConnection();			
		}
		
		/**
		 *  This function defines, how the slides have to be sorted.
		 */
		public function sortOnTime(a:TimeStep, b:TimeStep):Number
		{
		    var aTimeStep:Number = a.getTime();
		    var bTimeStep:Number = b.getTime();
		
		    if(aTimeStep > bTimeStep) return 1;
		    else if(aTimeStep < bTimeStep) return -1;
		    else return 0; //aSlide == bSlide
		}	
		
		
		/**
		 * This function gives back the slide to a given time.
		 * If the time is before the timestep of the first slide, the timestep of the first 
		 * slide is given back.
		 * 
		 * @parameters time
		 * 
		 * @return TimeStep
		 */
		public function getTimeStepByTime(time:int):TimeStep
		{			
			var found:TimeStep = timeSteps[0]; 
			for(var j:int=0;j<timeSteps.length;j++)
			{
				var pos:int=(lastJ+j)%timeSteps.length;
				var tmp:TimeStep = timeSteps[pos];
				var tmpNext:TimeStep =timeSteps[(lastJ+j+1)%timeSteps.length];
				if(tmp.getTime()<=time && time<tmpNext.getTime()){
					found=tmp;
					lastJ=pos;
					return found;
				}
			}
			
		    // Sonderfall 1. Folie:
		    var first:TimeStep = timeSteps[0]; 
			if(time<first.getTime()) return first;
			else // Sonderfall letzte Folie
				return timeSteps[timeSteps.length-1];			
			
			return found;
		}
		
		public function isErster(time:TimeStep):Boolean{
			
			
			if (timeSteps[1].getTime() > time.getTime())
				return true;
			else
				return false;
		}
		
		public function isLetzter(time:TimeStep):Boolean{
			if (timeSteps[timeSteps.length-2].getTime() < time.getTime())
				return true;
			else
				return false;
		}
		
		
		/**
		 * Gives the timeSteps array
		 * 
		 * @return Array TimeSteps Array 
		 */
		public function getTimeSteps():Array
		{
			return this.timeSteps;
		}
		
		/**
		 * Returns the animationSteps of a given slide
		 * 
		 * @return Array TimeSteps Array
		 */
		public function getAnimStepsOfASlide(slideID:int):Array{
			var temp:Array = new Array();
			for(var i:int=0;i<timeSteps.length;i++){
				
				if (TimeStep(timeSteps[i]).getID()==slideID){
					temp.push(timeSteps[i]);
				}	
			}
			return temp;
		}
		
		/**
		 * Gives the slides array
		 * 
		 * @return Array slides array
		 */
		public function getSlides():Array
		{
			return this.slides;
		}
		
		public function getLastSlide():TimeStep
		{
			return 	this.slides[slides.length-1];
		}
		
		
		/**
		 * Gives back the timestep of the previous slide.
		 * 
		 * @parameters time
		 * 
		 * @return TimeStep
		 */
		public function getPreviousSlideStep(time:int):TimeStep
		{
			var found:TimeStep=slides[0]; // vor erstem Step kommt wieder der erste Step (by Design)

			if(getTimeStepByTime(time).getAnimationStep()>0)
			{
				for(var j:int=1;j<slides.length;j++) 
				{
					var tmp:TimeStep = slides[j];
					if(tmp.getTime()<=time) found=slides[j];
					else break;
				}
			}
			else
			{
				for(var k:int=1;k<slides.length;k++) 
				{
					var tmp2:TimeStep = slides[k];
					if(tmp2.getTime()<=time) found=slides[k-1];
					else break;
				}
				
			} 
			return found;
		}
		
		/**
		 * Gives back the timeStep of the previous animationstep.
		 * 
		 * @parameters time
		 * 
		 * @return TimeStep
		 */		
		public function getPreviousStep(time:int):TimeStep
		{
			var found:TimeStep = timeSteps[0]; // vor erstem Step kommt wieder der erste Step (by Design)
			for(var j:int=1;j<timeSteps.length;j++) 
			{
				var tmp:TimeStep = timeSteps[j];
				if(tmp.getTime()<=time) found=timeSteps[j-1];
				else break;

			}
			return found; 
		}
		
		public function getCurrentStep(time:int):TimeStep{
			for(var j:int=0;j<timeSteps.length-1;j++)
			{
				var tmp:TimeStep = timeSteps[j];
				if(tmp.getTime()>time) return timeSteps[j-1];
				
			}
			return 	timeSteps[timeSteps.length-1];
		}
		
		
		public function getNextStep(time:int):TimeStep
		{
			for(var j:int=0;j<timeSteps.length-1;j++)
			{
				var tmp:TimeStep = timeSteps[j];
				if(tmp.getTime()>time) return tmp;

			}
			return 	timeSteps[timeSteps.length-1]; // nach letztem Step kommt wieder der letzte Step (by Design)
		}
		
		/**
		 * Gives back the timeStep of the next slide.
		 * 
		 * @parameters time
		 * 
		 * @return TimeStep
		 */		
		public function getNextSlideStep(time:int):TimeStep
		{
			for(var j:int=0;j<slides.length-1;j++)
			{
				var tmp:TimeStep = slides[j];
				if(tmp.getTime()>time) return tmp;

			}
			return 	slides[slides.length-1]; // nach letztem Step kommt wieder der letzte Step (by Design)
		}
		
		/** 
		 * Creates the slide array that contains the timesteps of the slides.
		 */
		public function extractSlides():void
		{
			var last:int=-1;
			slides = new Array();
			for(var j:int=0;j<timeSteps.length;j++) 
			{
				var tmp:TimeStep = timeSteps[j];
				if(tmp.getID()!=last)
				{
					slides.push(tmp);
					last=tmp.getID();
				}
			}
		}		
		
		/**
		 * Delivers true if mouse.xml is loaded and available. 
		 */
		public function isMouseXMLAvailable():Boolean
		{
			return this.mouseXMLAvailable;
		}		
		
		/**
		 * Delivers the mousestep for a given time. 
		 * 
		 * @parameters time
		 * 
		 * @return MouseStep
		 */
		public function getMouseStepByTime(time:int):MouseStep
		{
			var found:MouseStep = mouseSteps[0]; 
			for(var j:int=0;j<mouseSteps.length;j++)
			{
				var pos:int=(lastJMouseXML+j)%mouseSteps.length;
				var tmp:MouseStep = mouseSteps[pos];
				var tmpNext:MouseStep = mouseSteps[(lastJMouseXML+j+1)%mouseSteps.length];
				if(tmp.time<=time && time<tmpNext.time){
					found=tmp;
					lastJMouseXML=pos;
					return found;
				}
			}
			
		    // Sonderfall 1. MouseStep:
		    var first:MouseStep = mouseSteps[0]; 
			if(time<first.time) return first;
			else // Sonderfall letzter MouseStep
				return mouseSteps[mouseSteps.length-1];
			return found;
		}
		
		/**
		 * Returns the index of the currently shown slide in the slides Array
		 * */
		public function getSlideIndexByTime(time:int):int{
			
			for(var j:int=0;j<slides.length-1;j++)
			{
				var tmp:TimeStep = slides[j];
				
				var tmpNext:TimeStep = slides[j+1];
				
				if(tmp.getTime()<=time && time<tmpNext.getTime()){
					return j;
				}
			}
			
			 // Special case 1. slide:
		    var first:TimeStep = slides[0]; 
			if(time<first.getTime()) return 0;
			else // special case last slide
				return slides.length-1;			
			
			return 0;
		
		}
	}
}